// using System.Collections;
// using System.Collections.Generic;
// using UnityEngine;
// using System.Threading;

// namespace JPS {
// 	public class GoalBounding {
// 		int width, height;
// 		bool[,] grid;

//         public Vector4[,][] bounding;

//         public GoalBounding(bool[,] navigable) {
// 			width = navigable.GetUpperBound(0) + 1;
// 			height = navigable.GetUpperBound(1) + 1;
// 			grid = navigable;
// 			bounding = null;
// 			doneThreadCount = 0;
// 		}

//         internal bool IsCellInBoundingBox(Vector2Int pos, JPSDir dir, Vector2Int target) {
// 			if (bounding == null)
// 				return true;
// 			Vector4 bb = bounding[pos.x, pos.y][(int)dir];
// 			if (target.x >= bb.x && target.x <= bb.y &&
// 				target.y >= bb.z && target.y <= bb.w)
// 				return true;
// 			return false;
// 		}


//         int doneThreadCount;
// 		public bool Done => doneThreadCount == width * height;
// 		public int DoneThreadCount => doneThreadCount;

//         public void Create() {
// 			doneThreadCount = 0;
// 			bounding = new Vector4[width, height][];
// 			for (int x = 0; x < width; x++)
// 				for (int y = 0; y < height; y++)
// 					ThreadPool.QueueUserWorkItem(new WaitCallback(FloodFill), new Vector2Int(x, y));
// 			//FloodFill(new Vector2Int(0, 0));
// 		}

//         private void FloodFill(object param) {
// 			// 先初始化一下
// 			Vector2Int pos = (Vector2Int)param;
// 			var lrbts = new Vector4[8];
// 			for (int i = 0; i < 8; i++) {
// 				Vector2Int npos = pos + JPSUtils.DirToVec[i];
// 				lrbts[i] = new Vector4(npos.x, npos.x, npos.y, npos.y);
// 			}
// 			if (grid[pos.x, pos.y] == false) {
// 				bounding[pos.x, pos.y] = lrbts;
// 				Interlocked.Increment(ref doneThreadCount);
// 				return;
// 			}
// 			// 先填充一个场景
// 			MyPriorityQueue<FloodFillCell> _open = new MyPriorityQueue<FloodFillCell>((width + height) * 2);
// 			MyPriorityQueue<FloodFillCell> _closed = new MyPriorityQueue<FloodFillCell>((width + height) * 2);
// 			FloodFillCell[,] ffGrid = new FloodFillCell[width, height];
// 			for (int x = 0; x < width; x++)
// 				for (int y = 0; y < height; y++) {
// 					ffGrid[x, y] = new FloodFillCell() {
// 						pos = new Vector2Int(x, y),
// 						available = grid[x, y],
// 						flag = -1,
// 						givenCost = 0,
// 						Closed = new bool[] { false, false, false, false, false, false, false, false }
// 					};
// 				}
// 			// 走一趟FloodFill标记场景内的区域
// 			for (int dirIdx = 0; dirIdx < 8; dirIdx++)
// 				Fill(dirIdx, pos, ref _open, ref _closed, ref ffGrid);
// 			// 统计各方向的BB
// 			foreach (var cell in ffGrid) {
// 				int flag = cell.flag;
// 				if (flag == -1)
// 					continue;
// 				Vector4 bb = lrbts[flag];
// 				if (bb.x > cell.pos.x)
// 					bb.x = cell.pos.x;
// 				if (bb.y < cell.pos.x)
// 					bb.y = cell.pos.x;
// 				if (bb.z > cell.pos.y)
// 					bb.z = cell.pos.y;
// 				if (bb.w < cell.pos.y)
// 					bb.w = cell.pos.y;
// 				lrbts[flag] = bb;
// 			}
// 			bounding[pos.x, pos.y] = lrbts;
// 			// 完事，原子操作下Flag
// 			Interlocked.Increment(ref doneThreadCount);
// 			if (Done) {
// 				Debug.Log("Done");
// 			}
// 		}

//         private FloodFillCell _N(Vector2Int pos, ref FloodFillCell[,] ffGrid) {
// 			if (pos.x < 0 || pos.x >= width || pos.y < 0 || pos.y >= height)
// 				return null;
// 			return ffGrid[pos.x, pos.y];
// 		}

//         private FloodFillCell UpdateNeighbor(Vector2Int pos, int flag, int dir, float cost,
// 			ref FloodFillCell[,] ffGrid) {
// 			var neighbor = _N(pos + JPSUtils.DirToVec[dir], ref ffGrid);
// 			if (neighbor == null || !CanNavigate(pos, dir, ref ffGrid) || !neighbor.available) return null;
// 			// 更新代价
// 			FloodFillCell res = neighbor;
// 			if (neighbor.Closed[(int)flag])
// 				res = null;
// 			// 如果已经被标记，就只更新代价
// 			if ((neighbor.flag == -1) ||
// 				(neighbor.flag != -1 && cost < neighbor.givenCost)) {
// 				neighbor.givenCost = cost;
// 				neighbor.flag = (int)flag;
// 			}
// 			neighbor.Closed[(int)flag] = true;
// 			return res;
// 		}

//         private bool CanNavigate(Vector2Int src, int dirIdx, ref FloodFillCell[,] ffGrid) {
// 			if (dirIdx <= 3) return true;
// 			FloodFillCell c0, c1;
// 			if (dirIdx == (int)JPSDir.NW) {
// 				c0 = _N(src + JPSUtils.DirToVec[(int)JPSDir.N], ref ffGrid);
// 				c1 = _N(src + JPSUtils.DirToVec[(int)JPSDir.W], ref ffGrid);
// 			} else if (dirIdx == (int)JPSDir.NE) {
// 				c0 = _N(src + JPSUtils.DirToVec[(int)JPSDir.N], ref ffGrid);
// 				c1 = _N(src + JPSUtils.DirToVec[(int)JPSDir.E], ref ffGrid);
// 			} else if (dirIdx == (int)JPSDir.SW) {
// 				c0 = _N(src + JPSUtils.DirToVec[(int)JPSDir.S], ref ffGrid);
// 				c1 = _N(src + JPSUtils.DirToVec[(int)JPSDir.W], ref ffGrid);
// 			} else {
// 				c0 = _N(src + JPSUtils.DirToVec[(int)JPSDir.S], ref ffGrid);
// 				c1 = _N(src + JPSUtils.DirToVec[(int)JPSDir.E], ref ffGrid);
// 			}
// 			if (c0.available && c1.available)
// 				return true;
// 			return false;
// 		}

//         private void Fill(int dirIdx, Vector2Int pos,
// 			ref MyPriorityQueue<FloodFillCell> _open,
// 			ref MyPriorityQueue<FloodFillCell> _closed,
// 			ref FloodFillCell[,] ffGrid) {
// 			_open.Clear();
// 			_closed.Clear();
// 			Vector2Int start = pos + JPSUtils.DirToVec[dirIdx];
// 			var startCell = _N(start, ref ffGrid);
// 			if (startCell == null || !CanNavigate(pos, dirIdx, ref ffGrid) || !startCell.available)
// 				return;
// 			startCell.flag = dirIdx;
// 			startCell.givenCost = 0;
// 			_open.Enqueue(startCell, startCell.givenCost);
// 			while (_open.Count != 0) {
// 				FloodFillCell current = _open.Dequeue();
// 				current.Closed[dirIdx] = true;
// 				for (int d = 0; d < 8; d++) {
// 					var neighbour = UpdateNeighbor(current.pos,
// 						dirIdx,
// 						d,
// 						current.givenCost + (d <= 3 ? 1 : JPSUtils.SQRT2),
// 						ref ffGrid);
// 					if (neighbour != null)
// 						_open.Enqueue(neighbour, neighbour.givenCost);
// 				}
// 			}
// 		}

//         private class FloodFillCell : MyPriorityQueue {
// 			public Vector2Int pos;
// 			public int flag;
// 			public bool available;
// 			public float givenCost;
// 			public bool[] Closed;
// 		}
// 	}
// }